import { sys } from "cc";
import { PREVIEW } from "cc/env";

/** cocos本地存储器拓展 */
export default class StorageExt {

    /** key添加【游戏/用户】标识，便于本地区分存储 */
    private static fixKey(key: string, game?: string | number, user?: string | number): string {
        if (!key || key.trim().length == 0)
            return;
        key = key.trim();

        if (game != undefined || game != null) {
            if (typeof game == "number")
                game = game.toString();
            game = game.trim();
            if (!!game)
                key += "_GID[" + game + ']';
        }
        if (user != undefined || user != null) {
            if (typeof user == "number")
                user = user.toString();
            user = user.trim();
            if (!!user)
                key += "_UID[" + user + ']';
        }

        return key;
    }

    /**
     * Removes all key/value pairs, if there are any.
     *
     * Dispatches a storage event on Window objects holding an equivalent Storage object.
     */
    static clear(): void {
        sys.localStorage.clear();
    }

    /** Returns the number of key/value pairs. */
    static get size(): number {
        return sys.localStorage.length;
    }

    /** Returns the name of the nth key, or null if n is greater than or equal to the number of key/value pairs. */
    static key(index: number): string | null {
        return sys.localStorage.key(index);
    }

    /**
     * Removes the key/value pair with the given key, if a key/value pair with the given key exists.
     * @param key 原始键
     * @param game 区分游戏
     * @param user 区分用户
     */
    static removeItem(key: string, game?: string | number, user?: string | number): void {
        key = this.fixKey(key, game, user);
        if (!!key)
            sys.localStorage.removeItem(key);
    }

    /**
     * Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.
     * @param key 原始键
     * @param value [string | number | boolean | Object] 原始值
     * @param game 区分游戏
     * @param user 区分用户
     * @returns 
     */
    static setItem(key: string, value: string | number | boolean | Object, game?: string | number, user?: string | number): void {
        if (value === null || value === undefined)
            return;
        key = this.fixKey(key, game, user);
        if (!key) return;

        let str: string = "";
        switch (typeof value) {
            case "string":
                str = value;
                break;
            case "number":
                str = value.toString();
                break;
            case "boolean":
                str = (value ? 1 : 0).toString();
                break;
            case "object":
                str = JSON.stringify(value);
                break;
        }
        PREVIEW && console.log(`[StorageExt] 存入数据 key: ${key}, value: ${str}`);
        sys.localStorage.setItem(key, str);
    }

    /**
     * Returns the current value associated with the given key, or null if the given key does not exist.
     * @param key 原始键
     * @param game 区分游戏
     * @param user 区分用户
     * @returns 
     */
    static getItem(key: string, game?: string | number, user?: string | number): string | null {
        key = this.fixKey(key, game, user);
        if (!key)
            return null;
        return sys.localStorage.getItem(key);
    }

    /**
     * Returns the current value associated with the given key, or null if the given key does not exist.
     * @param key 原始键
     * @param def 默认值 (当查询不到数值时作为返回def；若未定义def，则返回null)
     * @param game 区分游戏
     * @param user 区分用户
     * @returns 
     */
    static getNum(key: string, def?: number, game?: string | number, user?: string | number): number | null {
        const value: string | null = this.getItem(key, game, user);
        if (value != null) {
            if (value.indexOf(".") >= 0)
                return parseFloat(value);
            return parseInt(value);
        }
        if (def != undefined || def != null)
            return def;
        else
            return null;
    }

    /**
     * Returns the current value associated with the given key, or null if the given key does not exist.
     * @param key 原始键
     * @param def 默认值 (当查询不到数值时作为返回def；若未定义def，则返回null)
     * @param game 区分游戏
     * @param user 区分用户
     * @returns 
     */
    static getBool(key: string, def?: boolean, game?: string | number, user?: string | number): boolean | null {
        const value: number | null = this.getNum(key, undefined, game, user);
        if (value != null) {
            return value != 0;
        }
        if (def != undefined || def != null)
            return !!def;
        else
            return null;
    }

    /**
     * Returns the current value associated with the given key, or null if the given key does not exist.
     * @param key 原始键
     * @param game 区分游戏
     * @param user 区分用户
     * @returns 
     */
    static getObj(key: string, game?: string | number, user?: string | number): number | null {
        const value: string | null = this.getItem(key, game, user);
        if (value != null) {
            try {
                return JSON.parse(value);
            } catch (error) {
                console.error("[StorageExt] JSON.parse string=", value);
                return null;
            }
        }
        return null;
    }

}
if (PREVIEW)
    globalThis.StorageExt = StorageExt;